package br.ufpe.cin.rdfilter.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;

@SuppressWarnings("serial")
public class FrequencyList<V> extends HashMap<V, Integer>{
	
	public void insertFrequency(V element){
		if(containsKey(element)){ // if the element exists
			Integer frequency = this.remove(element);
			this.put(element, frequency + 1); // re-insert the element with the frequency incremented
		}
		else{ // if the element doesn't exist, insert into the hash map
			this.put(element, 1);
		}
	}
	
	/**
	 * 
	 * @return list of the hash map' keys sorted by values, the frequency of its.
	 */
	public ArrayList<V> getSortedList(){
		 
		 ArrayList<V> sortedList = new ArrayList<V>();
		 HashMap<V,Integer> sortedMap = this.getSortedHashMap();
		 
		 Set<V> elements = sortedMap.keySet();
		 
		 // inserting the elements from the sorted hash map into the return list
		 for(V element: elements){
			 sortedList.add(0,element);			 			 
		 }
		 
		 return sortedList;
	}
	
	private HashMap<V, Integer> getSortedHashMap(){
	   
		List<V> mapKeys = new ArrayList<V>(this.keySet());
	    List<Integer> mapValues = new ArrayList<Integer>(this.values());
	    
	    //sorting the hash map's values
	    Collections.sort(mapValues);
	        
	    LinkedHashMap<V, Integer> sortedHashMap = new LinkedHashMap<V, Integer>();
	    
	    Iterator<Integer> valueIt = mapValues.iterator();
	    
	    // inserting the values neatly into the sorted hash map
	    while (valueIt.hasNext()) {
	        Object val = valueIt.next();
	        Iterator<V> keyIt = mapKeys.iterator();
	        
	        while (keyIt.hasNext()) {
	            V key = keyIt.next();
	            String comp1 = this.get(key).toString();
	            String comp2 = val.toString();
	            
	            if (comp1.equals(comp2)){
	                mapKeys.remove(key);
	                sortedHashMap.put(key, (Integer)val);
	                break;
	            }
	        }
	    }
	    
	    return sortedHashMap;
		
	}
	
}
